using Microsoft.SqlServer.Tools.PublishWizard.Helpers;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Xml;

namespace Microsoft.SqlServer.Management.SqlManagerUI.Scripting
{
	internal static class HostingConfigurationManager
	{
		private const string _settingsElementName = "settings";

		private const string _hosterElementName = "hoster";

		private const string _webServiceAddressElementName = "web_service_address";

		private const string _hosterNameElementName = "name";

		private const string _hosterFileNameElementName = "filename";

		private const string _sqlUserNameElementName = "sql_username";

		private const string _sqlPasswordElementName = "sql_password";

		private const string _userNameElementName = "username";

		private const string _passwordElementName = "password";

		private const string _databaseInfoElementName = "database";

		private const string _sqlServerElementName = "server_name";

		private const string _databaseElementName = "database_name";

		private const string _databaseDefaultAttributeName = "default";

		private static Dictionary<string, byte> _byteLookupDictionary;

		private static readonly string _publishingWizardDirectory = Path.Combine(Path.Combine(Path.Combine(Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Microsoft"), "Microsoft SQL Server"), "90"), "Tools"), "Publishing Wizard");

		private static Dictionary<string, byte> ByteLookupTable
		{
			get
			{
				if (HostingConfigurationManager._byteLookupDictionary == null)
				{
					HostingConfigurationManager._byteLookupDictionary = new Dictionary<string, byte>();
					for (int i = 0; i <= 255; i++)
					{
						if (i < 16)
						{
							HostingConfigurationManager._byteLookupDictionary[string.Format(CultureInfo.InvariantCulture, "0{0:X}", new object[]
							{
								(byte)i
							})] = (byte)i;
						}
						else
						{
							HostingConfigurationManager._byteLookupDictionary[string.Format(CultureInfo.InvariantCulture, "{0:X}", new object[]
							{
								(byte)i
							})] = (byte)i;
						}
					}
				}
				return HostingConfigurationManager._byteLookupDictionary;
			}
		}

		internal static string UserConfigPath
		{
			get
			{
				return Path.Combine(HostingConfigurationManager._publishingWizardDirectory, "user.config");
			}
		}

		internal static ProviderCollection LoadProvidersFromDisk()
		{
			ProviderCollection providerCollection = new ProviderCollection();
			if (!File.Exists(HostingConfigurationManager.UserConfigPath))
			{
				HostingConfigurationManager.CreateNewUserConfiguration();
			}
			XmlDocument xmlDocument = HostingConfigurationManager.LoadXmlDocumentFromFile(HostingConfigurationManager.UserConfigPath);
			XmlElement documentElement = xmlDocument.DocumentElement;
			if (documentElement == null || !documentElement.Name.Equals("settings"))
			{
				throw new XmlException(string.Format(CultureInfo.CurrentCulture, ScriptingEngineResources.ERROR_UserConfigCorrupt, new object[]
				{
					HostingConfigurationManager.UserConfigPath
				}));
			}
			foreach (XmlNode xmlNode in documentElement.ChildNodes)
			{
				if (xmlNode.Name.Equals("hoster") && xmlNode is XmlElement)
				{
					XmlElement hosterElement = (XmlElement)xmlNode;
					string providerName = HostingConfigurationManager.ReadChildStringValue(hosterElement, "name");
					string filePath = HostingConfigurationManager.ReadChildStringValue(hosterElement, "filename");
					ProviderEntity providerEntity = new ProviderEntity(providerName, filePath);
					providerCollection.Add(providerEntity);
					try
					{
						HostingConfigurationManager.ReadHosterConfigurationFile(providerEntity);
					}
					catch (Exception ex)
					{
						providerEntity.ErrorMessage = string.Format(CultureInfo.CurrentCulture, ScriptingEngineResources.ERROR_ReadingHostingProviderFailed, new object[]
						{
							providerEntity.Name,
							providerEntity.FilePath,
							ex.ToString()
						});
					}
				}
			}
			return providerCollection;
		}

		internal static void AddProvider(ProviderEntity provider)
		{
			HostingConfigurationManager.ValidateProvider(provider);
			XmlDocument xmlDocument = HostingConfigurationManager.CreateHosterXmlDocument(provider);
			provider.FilePath = HostingConfigurationManager.GetNewFilePath(provider.Name);
			using (FileStream fileStream = new FileStream(provider.FilePath, FileMode.CreateNew, FileAccess.Write))
			{
				xmlDocument.Save(fileStream);
			}
			HostingConfigurationManager.AddProviderSectionToUserConfig(provider);
		}

		internal static void DeleteProvider(ProviderEntity provider)
		{
			ArgumentValidationHelpers.ValidateNotNull(provider, "provider");
			if (string.IsNullOrEmpty(provider.FilePath))
			{
				return;
			}
			XmlDocument xmlDocument = HostingConfigurationManager.LoadXmlDocumentFromFile(HostingConfigurationManager.UserConfigPath);
			XmlElement xmlElement = HostingConfigurationManager.FindHosterWithFilePath(provider.FilePath, xmlDocument);
			if (xmlElement != null)
			{
				xmlDocument.DocumentElement.RemoveChild(xmlElement);
			}
			HostingConfigurationManager.WriteUserConfigToDisk(xmlDocument);
			try
			{
				File.Delete(provider.FilePath);
			}
			catch (Exception)
			{
			}
		}

		internal static void UpdateProvider(ProviderEntity provider)
		{
			HostingConfigurationManager.ValidateProvider(provider);
			XmlDocument userConfigDocument = HostingConfigurationManager.LoadXmlDocumentFromFile(HostingConfigurationManager.UserConfigPath);
			XmlElement xmlElement = HostingConfigurationManager.FindHosterWithFilePath(provider.FilePath, userConfigDocument);
			if (xmlElement == null)
			{
				HostingConfigurationManager.AddProvider(provider);
				return;
			}
			if (string.IsNullOrEmpty(provider.FilePath))
			{
				provider.FilePath = HostingConfigurationManager.GetNewFilePath(provider.Name);
			}
			XmlDocument xmlDocument = HostingConfigurationManager.CreateHosterXmlDocument(provider);
			using (FileStream fileStream = new FileStream(provider.FilePath, FileMode.Create, FileAccess.Write))
			{
				xmlDocument.Save(fileStream);
			}
			HostingConfigurationManager.UpdateElement(userConfigDocument, xmlElement, "name", provider.Name);
			HostingConfigurationManager.UpdateElement(userConfigDocument, xmlElement, "filename", provider.FilePath);
			HostingConfigurationManager.WriteUserConfigToDisk(userConfigDocument);
		}

		internal static void CreateNewUserConfiguration()
		{
			if (!Directory.Exists(HostingConfigurationManager._publishingWizardDirectory))
			{
				Directory.CreateDirectory(HostingConfigurationManager._publishingWizardDirectory);
			}
			XmlDocument xmlDocument = new XmlDocument();
			xmlDocument.AppendChild(xmlDocument.CreateXmlDeclaration("1.0", "utf-8", null));
			xmlDocument.AppendChild(xmlDocument.CreateElement("settings"));
			HostingConfigurationManager.WriteUserConfigToDisk(xmlDocument);
		}

		private static void ValidateProvider(ProviderEntity provider)
		{
			ArgumentValidationHelpers.ValidateNotNull(provider, "provider");
			ArgumentValidationHelpers.ValidateStringNotNullOrEmpty(provider.Name, "provider.Name");
			ArgumentValidationHelpers.ValidateStringNotNullOrEmpty(provider.WebServiceAddress, "provider.WebServiceAddress");
			foreach (DatabaseEntity current in provider.Databases)
			{
				ArgumentValidationHelpers.ValidateStringNotNullOrEmpty(current.DatabaseName, "database.DatabaseName");
				ArgumentValidationHelpers.ValidateStringNotNullOrEmpty(current.ServerName, "database.ServerName");
			}
		}

		private static void UpdateElement(XmlDocument userConfigDocument, XmlElement matchingNode, string elementName, string newValue)
		{
			XmlNodeList elementsByTagName = matchingNode.GetElementsByTagName(elementName);
			for (int i = 0; i < elementsByTagName.Count; i++)
			{
				matchingNode.RemoveChild(elementsByTagName[i]);
			}
			HostingConfigurationManager.AddElement(userConfigDocument, matchingNode, elementName, newValue);
		}

		private static XmlElement FindHosterWithFilePath(string hosterFileName, XmlDocument userConfigDocument)
		{
			XmlNodeList elementsByTagName = userConfigDocument.DocumentElement.GetElementsByTagName("hoster");
			XmlElement result = null;
			foreach (XmlNode xmlNode in elementsByTagName)
			{
				if (xmlNode is XmlElement)
				{
					XmlElement xmlElement = (XmlElement)xmlNode;
					string text = HostingConfigurationManager.ReadChildStringValue(xmlElement, "filename");
					if (text.Equals(hosterFileName, StringComparison.OrdinalIgnoreCase))
					{
						result = xmlElement;
						break;
					}
				}
			}
			return result;
		}

		private static void AddProviderSectionToUserConfig(ProviderEntity provider)
		{
			if (!File.Exists(HostingConfigurationManager.UserConfigPath))
			{
				HostingConfigurationManager.CreateNewUserConfiguration();
			}
			XmlDocument xmlDocument = new XmlDocument();
			xmlDocument.Load(HostingConfigurationManager.UserConfigPath);
			XmlElement xmlElement = xmlDocument.CreateElement("hoster");
			xmlDocument.DocumentElement.AppendChild(xmlElement);
			HostingConfigurationManager.AddElement(xmlDocument, xmlElement, "name", provider.Name);
			HostingConfigurationManager.AddElement(xmlDocument, xmlElement, "filename", provider.FilePath);
			HostingConfigurationManager.WriteUserConfigToDisk(xmlDocument);
		}

		private static void WriteUserConfigToDisk(XmlDocument userConfigDocument)
		{
			using (FileStream fileStream = new FileStream(HostingConfigurationManager.UserConfigPath, FileMode.Create, FileAccess.Write))
			{
				userConfigDocument.Save(fileStream);
			}
		}

		private static void ReadHosterConfigurationFile(ProviderEntity provider)
		{
			if (!File.Exists(provider.FilePath))
			{
				throw new FileNotFoundException(ScriptingEngineResources.ERROR_HostingProviderFileNotFound);
			}
			XmlDocument xmlDocument = HostingConfigurationManager.LoadXmlDocumentFromFile(provider.FilePath);
			XmlElement documentElement = xmlDocument.DocumentElement;
			if (documentElement == null || !documentElement.Name.Equals("hoster"))
			{
				throw new XmlException(ScriptingEngineResources.ERROR_ConfigurationDataCorrupt);
			}
			provider.WebServiceAddress = HostingConfigurationManager.ReadChildStringValue(documentElement, "web_service_address");
			provider.UserName = HostingConfigurationManager.ReadChildStringValue(documentElement, "username", false);
			provider.Password = HostingConfigurationManager.ReadPasswordField(documentElement, "password");
			provider.SavePassword = !string.IsNullOrEmpty(provider.Password);
			XmlNodeList elementsByTagName = documentElement.GetElementsByTagName("database");
			foreach (XmlNode xmlNode in elementsByTagName)
			{
				DatabaseEntity databaseEntity = new DatabaseEntity();
				if (xmlNode.Attributes.Count > 0)
				{
					foreach (XmlAttribute xmlAttribute in xmlNode.Attributes)
					{
						if (xmlAttribute.Name.Equals("default"))
						{
							databaseEntity.IsDefault = xmlAttribute.Value.Equals(true.ToString(), StringComparison.OrdinalIgnoreCase);
						}
					}
				}
				XmlElement xmlElement = (XmlElement)xmlNode;
				databaseEntity.ServerName = HostingConfigurationManager.ReadChildStringValue(xmlElement, "server_name");
				databaseEntity.DatabaseName = HostingConfigurationManager.ReadChildStringValue(xmlElement, "database_name");
				databaseEntity.UserName = HostingConfigurationManager.ReadChildStringValue(xmlElement, "sql_username", false);
				databaseEntity.Password = HostingConfigurationManager.ReadPasswordField(xmlElement, "sql_password");
				databaseEntity.SavePassword = !string.IsNullOrEmpty(databaseEntity.Password);
				provider.Databases.Add(databaseEntity);
			}
		}

		private static XmlDocument LoadXmlDocumentFromFile(string filePath)
		{
			XmlDocument result;
			using (XmlReader xmlReader = XmlReader.Create(filePath, new XmlReaderSettings
			{
				IgnoreComments = true,
				IgnoreWhitespace = true
			}))
			{
				XmlDocument xmlDocument = new XmlDocument();
				xmlDocument.Load(xmlReader);
				result = xmlDocument;
			}
			return result;
		}

		private static string ReadChildStringValue(XmlElement hosterElement, string childName)
		{
			return HostingConfigurationManager.ReadChildStringValue(hosterElement, childName, true);
		}

		private static string ReadChildStringValue(XmlElement hosterElement, string childName, bool childRequired)
		{
			XmlNodeList elementsByTagName = hosterElement.GetElementsByTagName(childName);
			if (elementsByTagName.Count == 1 && elementsByTagName[0].ChildNodes.Count == 1)
			{
				return elementsByTagName[0].ChildNodes[0].Value;
			}
			if (childRequired)
			{
				throw new XmlException(ScriptingEngineResources.ERROR_ConfigurationDataCorrupt);
			}
			return string.Empty;
		}

		private static string ReadPasswordField(XmlElement xmlElement, string elementName)
		{
			XmlNodeList elementsByTagName = xmlElement.GetElementsByTagName(elementName);
			if (elementsByTagName.Count == 0)
			{
				return string.Empty;
			}
			if (elementsByTagName.Count != 1)
			{
				throw new XmlException(ScriptingEngineResources.ERROR_ConfigurationDataCorrupt);
			}
			if (elementsByTagName[0].ChildNodes.Count == 1 && elementsByTagName[0].ChildNodes[0] is XmlCDataSection)
			{
				string value = elementsByTagName[0].ChildNodes[0].Value;
				if (!string.IsNullOrEmpty(value))
				{
					return HostingConfigurationManager.DecryptPassword(value);
				}
			}
			return string.Empty;
		}

		private static XmlDocument CreateHosterXmlDocument(ProviderEntity provider)
		{
			XmlDocument xmlDocument = new XmlDocument();
			xmlDocument.AppendChild(xmlDocument.CreateXmlDeclaration("1.0", "utf-8", null));
			XmlElement xmlElement = xmlDocument.CreateElement("hoster");
			xmlDocument.AppendChild(xmlElement);
			HostingConfigurationManager.AddElement(xmlDocument, xmlElement, "web_service_address", provider.WebServiceAddress);
			HostingConfigurationManager.AddElement(xmlDocument, xmlElement, "username", provider.UserName);
			if (provider.SavePassword)
			{
				HostingConfigurationManager.AddPasswordElement(xmlDocument, xmlElement, "password", provider.Password);
			}
			else
			{
				HostingConfigurationManager.AddPasswordElement(xmlDocument, xmlElement, "password", "");
			}
			foreach (DatabaseEntity current in provider.Databases)
			{
				XmlElement xmlElement2 = xmlDocument.CreateElement("database");
				xmlElement.AppendChild(xmlElement2);
				XmlAttribute xmlAttribute = xmlDocument.CreateAttribute("default");
				xmlAttribute.Value = current.IsDefault.ToString();
				xmlElement2.Attributes.Append(xmlAttribute);
				HostingConfigurationManager.AddElement(xmlDocument, xmlElement2, "server_name", current.ServerName);
				HostingConfigurationManager.AddElement(xmlDocument, xmlElement2, "database_name", current.DatabaseName);
				HostingConfigurationManager.AddElement(xmlDocument, xmlElement2, "sql_username", current.UserName);
				if (current.SavePassword)
				{
					HostingConfigurationManager.AddPasswordElement(xmlDocument, xmlElement2, "sql_password", current.Password);
				}
				else
				{
					HostingConfigurationManager.AddPasswordElement(xmlDocument, xmlElement2, "sql_password", "");
				}
			}
			return xmlDocument;
		}

		private static void AddElement(XmlDocument hosterDocument, XmlElement hoster, string elementName, string elementValue)
		{
			XmlElement xmlElement = hosterDocument.CreateElement(elementName);
			xmlElement.AppendChild(hosterDocument.CreateTextNode(elementValue));
			hoster.AppendChild(xmlElement);
		}

		private static void AddPasswordElement(XmlDocument xmlDocument, XmlElement xmlElement, string passwordElementName, string password)
		{
			if (!string.IsNullOrEmpty(password))
			{
				string text = HostingConfigurationManager.EncryptPassword(password);
				if (text == null)
				{
					return;
				}
				XmlCDataSection newChild = xmlDocument.CreateCDataSection(text);
				XmlElement xmlElement2 = xmlDocument.CreateElement(passwordElementName);
				xmlElement2.AppendChild(newChild);
				xmlElement.AppendChild(xmlElement2);
			}
		}

		private static string EncryptPassword(string password)
		{
			try
			{
				byte[] bytes = Encoding.Unicode.GetBytes(password);
				byte[] array = ProtectedData.Protect(bytes, null, DataProtectionScope.CurrentUser);
				StringBuilder stringBuilder = new StringBuilder();
				byte[] array2 = array;
				for (int i = 0; i < array2.Length; i++)
				{
					byte b = array2[i];
					string value;
					if (b < 16)
					{
						value = string.Format(CultureInfo.InvariantCulture, "0{0:X}", new object[]
						{
							b
						});
					}
					else
					{
						value = string.Format(CultureInfo.InvariantCulture, "{0:X}", new object[]
						{
							b
						});
					}
					stringBuilder.Append(value);
				}
				return stringBuilder.ToString();
			}
			catch (Exception)
			{
			}
			return null;
		}

		private static string DecryptPassword(string encryptedPassword)
		{
			try
			{
				string result;
				if (string.IsNullOrEmpty(encryptedPassword))
				{
					result = string.Empty;
					return result;
				}
				if (encryptedPassword.Length % 2 != 0)
				{
					result = string.Empty;
					return result;
				}
				byte[] array = new byte[encryptedPassword.Length / 2];
				int num = 0;
				while (num * 2 < encryptedPassword.Length)
				{
					array[num] = HostingConfigurationManager.ByteLookupTable[encryptedPassword.Substring(num * 2, 2)];
					num++;
				}
				byte[] bytes = ProtectedData.Unprotect(array, null, DataProtectionScope.CurrentUser);
				result = Encoding.Unicode.GetString(bytes);
				return result;
			}
			catch (Exception)
			{
			}
			return string.Empty;
		}

		private static string GetNewFilePath(string name)
		{
			if (!Directory.Exists(HostingConfigurationManager._publishingWizardDirectory))
			{
				Directory.CreateDirectory(HostingConfigurationManager._publishingWizardDirectory);
			}
			char[] invalidFileNameChars = Path.GetInvalidFileNameChars();
			char[] array = invalidFileNameChars;
			for (int i = 0; i < array.Length; i++)
			{
				char oldChar = array[i];
				name = name.Replace(oldChar, '~');
			}
			string str = name;
			string str2 = ".xml";
			string text = Path.Combine(HostingConfigurationManager._publishingWizardDirectory, str + str2);
			int j = 0;
			while (j < 1000)
			{
				if (!File.Exists(text))
				{
					return text;
				}
				j++;
				str = name + j;
				text = Path.Combine(HostingConfigurationManager._publishingWizardDirectory, str + str2);
			}
			str = name + Guid.NewGuid().ToString();
			return Path.Combine(HostingConfigurationManager._publishingWizardDirectory, str + str2);
		}
	}
}
